/////////////////////////////////////////////////////////////////////////////
// Name:        comdefs.h
// Purpose:     
// Author:      syy
// Modified by: 
// Created:     2020-02-25 17:55:24 
// RCS-ID:      
// Copyright:   
// Licence:     
/////////////////////////////////////////////////////////////////////////////
#ifndef _COMDEFS_H_
#define _COMDEFS_H_

#include <assert.h>

#if defined(WIN32)
#include <ObjBase.h>
#include <InitGuid.h>
#elif defined(CCORE_LINUX) || defined(CCORE_MAC) || defined(CCORE_ANDROID) || defined(CCORE_IOS)


typedef long HRESULT;
typedef void* LPVOID;


#define STDAPI extern "C" HRESULT

#define COM_DECLSPEC_NOTHROW
#define STDMETHODCALLTYPE
#define DECLSPEC_NOVTABLE

#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
#define STDMETHOD(method) virtual COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE method
#define STDMETHOD_(type,method) virtual COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE method
#define STDMETHODV(method) virtual COM_DECLSPEC_NOTHROW HRESULT STDMETHODVCALLTYPE method
#define STDMETHODV_(type,method) virtual COM_DECLSPEC_NOTHROW type STDMETHODVCALLTYPE method
#define PURE = 0
#define THIS_
#define THIS void
#define DECLARE_INTERFACE(iface) struct DECLSPEC_NOVTABLE iface
#define DECLARE_INTERFACE_(iface, baseiface) struct DECLSPEC_NOVTABLE iface : public baseiface
#define DECLARE_INTERFACE_IID(iface, iid) struct DECLSPEC_UUID(iid) DECLSPEC_NOVTABLE iface
#define DECLARE_INTERFACE_IID_(iface, baseiface, iid) struct DECLSPEC_UUID(iid) DECLSPEC_NOVTABLE iface : public baseiface

#if 0
	typedef struct _GUID {
		unsigned long  Data1;
		unsigned short Data2;
		unsigned short Data3;
		unsigned char  Data4[8];
	} GUID;

	typedef GUID IID;
	typedef GUID CLSID;

#	define REFIID const IID &
#	define REFCLSID const IID &

#	define DECLSPEC_SELECTANY
#	define FAR

#	define INITGUID
#	ifdef INITGUID
#	define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
		extern "C" const GUID DECLSPEC_SELECTANY name \
		= { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
#	else
#	define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
		extern "C" const GUID FAR name
#	endif // INITGUID
	inline int operator==(const GUID& guidOne, const GUID& guidOther)
	{
		return guidOne.Data1 == guidOther.Data1 &&
			guidOne.Data2 == guidOther.Data2 &&
			guidOne.Data3 == guidOther.Data3;
	}
#else
	typedef int GUID;
	typedef GUID IID;
	typedef GUID CLSID;
#	define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
#	define REFIID const IID &
#	define REFCLSID const IID &

#	define DECLSPEC_SELECTANY
#	define FAR

	enum
	{
		CLSID_DataCenter		= 0x0000, 
		IID_IDataCenter			= 0x0001,

        CLSID_FileModule		= 0x0010,
        IID_IFileModule			= 0x0011,

        CLSID_NetworkService	= 0x0020,
        IID_INetworkService		= 0x0021,

        CLSID_MessageKernel		= 0x0030,
        IID_IMessageKernel		= 0x0031,
		IID_IMessageSync		= 0x0032,
        IID_IMessageProcess		= 0x0033,
        IID_IMessageBond        = 0x0034,

        CLSID_HTTPKernel        = 0x0040,
        IID_IHttpKernel         = 0x0041,
        
        CLSID_DBModule			= 0x0050,
        IID_IDBModule			= 0x0051,

        CLSID_UIQB				= 0x0060,
        IID_IQBManager			= 0x0061,

		CLSID_Auth				= 0x0070,
		IID_IAuthLogin			= 0x0071,
	};
#endif


//-----------------------------------------------------------------------------
#ifdef __linux__
//#define CCORE_LINUX
#endif

#if defined(CCORE_LINUX) || defined(CCORE_ANDROID)
#include <inttypes.h>
#include <malloc.h>
#elif defined(CCORE_MAC) || defined(CCORE_IOS)
#include <libkern/OSAtomic.h>
#include <stdlib.h>
#endif

struct IUnknown
{
	virtual long STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) = 0;
	virtual unsigned long STDMETHODCALLTYPE AddRef(void) = 0;
	virtual unsigned long STDMETHODCALLTYPE Release(void) = 0;
};

#endif

template <typename T> class CUnknownObject : public T
{
public:
	CUnknownObject()
	{ 
		m_nRefCount = 0;
	}

	virtual ~CUnknownObject()
	{
		m_nRefCount = 0;
	}
	virtual long STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
	{
		*ppvObject = (T *)this;
		this->AddRef();
		return 0;
	}

	virtual unsigned long STDMETHODCALLTYPE AddRef(void)
	{
#if defined(WIN32)
		return static_cast<unsigned long>(InterlockedIncrement(
			reinterpret_cast<volatile long*>(&m_nRefCount)));
#elif defined(CCORE_MAC) || defined(CCORE_IOS)
		return ++m_nRefCount;//atomic_fetch_add(&m_nRefCount, 1);
#elif defined(CCORE_LINUX) || defined(CCORE_ANDROID)
		return __sync_fetch_and_add(&m_nRefCount, 1) + 1;
#else
		int ref = ++m_nRefCount;

		return static_cast<unsigned long>(ref);
#endif
	}

	virtual unsigned long STDMETHODCALLTYPE Release(void)
	{
#if defined(WIN32)
		long ref = static_cast<long>(InterlockedDecrement(
			reinterpret_cast<volatile long*>(&m_nRefCount)));
#elif defined(CCORE_MAC) || defined(CCORE_IOS)
		long ref = --m_nRefCount; //atomic_fetch_sub(&m_nRefCount, 1);
#elif defined(CCORE_LINUX) || defined(CCORE_ANDROID)
		long ref = __sync_fetch_and_sub(&m_nRefCount, 1) - 1;
#else
		long ref = --m_nRefCount;
#endif

		if (ref == 0)
		{
			delete this;
		}
		return static_cast<unsigned long>(ref);
	}

	long GetRef()
	{
		return m_nRefCount;
	}

private:
	int m_nRefCount;
};

// check return ptr
#define QB_CHECK_RETURN_PTR1(x) if (!(x)) \
{\
	return 0;\
}
#define QB_CHECK_RETURN_PTR2(x,y) if ((x) != (y)) \
{\
	return 0;\
}
#define QB_CHECK_RETURN_PTR_ASSERT1(x) if (!(x)) \
{\
	assert(0);\
	return 0;\
}
#define QB_CHECK_RETURN_PTR_ASSERT2(x,y) if ((x) != (y)) \
{\
	assert(0);\
	return 0;\
}

// check return int
#define QB_CHECK_RETURN_INT1(x) if (!(x)) \
{\
	return -1;\
}
#define QB_CHECK_RETURN_INT2(x,y) if ((x) != (y)) \
{\
	return -1;\
}
#define QB_CHECK_RETURN_INT_ASSERT1(x) if (!(x)) \
{\
	assert(0);\
	return -1;\
}
#define QB_CHECK_RETURN_INT_ASSERT2(x,y) if ((x) != (y)) \
{\
	assert(0);\
	return -1;\
}

// check return bool
#define QB_CHECK_RETURN_BOOL1(x) if (!(x)) \
{\
	return false;\
}
#define QB_CHECK_RETURN_BOOL2(x,y) if ((x) != (y)) \
{\
	return false;\
}
#define QB_CHECK_RETURN_BOOL_ASSERT1(x) if (!(x)) \
{\
	assert(0);\
	return false;\
}
#define QB_CHECK_RETURN_BOOL_ASSERT2(x,y) if ((x) != (y)) \
{\
	assert(0);\
	return false;\
}

// check return void
#define QB_CHECK_RETURN_VOID1(x) if (!(x)) \
{\
	return;\
}
#define QB_CHECK_RETURN_VOID2(x,y) if ((x) != (y)) \
{\
	return;\
}
#define QB_CHECK_RETURN_VOID_ASSERT1(x) if (!(x)) \
{\
	assert(0);\
	return;\
}
#define QB_CHECK_RETURN_VOID_ASSERT2(x,y) if ((x) != (y)) \
{\
	assert(0);\
	return;\
}

// check return value
#define QB_CHECK_RETURN_VALUE(x,retValue) if (!(x)) \
{\
	return retValue;\
}
#define QB_CHECK_RETURN_VALUE2(x,y,retValue) if ((x) != (y)) \
{\
	return retValue;\
}
#define QB_CHECK_RETURN_VALUE_ASSERT(x, retValue) if (!(x)) \
{\
	assert(0);\
	return retValue;\
}
#define QB_CHECK_RETURN_VALUE_ASSERT2(x,y,retValue) if ((x) != (y)) \
{\
	assert(0);\
	return retValue;\
}

// check break
#define QB_CHECK_RETURN_BREAK(x) if (!(x)) \
{\
	break;\
}
#define QB_CHECK_RETURN_BREAK_ASSERT(x) if (!(x)) \
{\
	assert(0);\
	break;\
}

// check continue
#define QB_CHECK_RETURN_CONTINUE(x) if (!(x)) \
{\
	continue;\
}
#define QB_CHECK_RETURN_CONTINUE_ASSERT(x) if (!(x)) \
{\
	assert(0);\
	continue;\
}

#endif // _COMDEFS_H_
